package multithread.framework.threadmethod;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Queue hold FutureTask
 * @author dailey_dai
 *
 * @param <V>
 */
public class FutureQueue<V> {
	ConcurrentLinkedQueue<Future<V>> futureQueue;
	Lock lock = null;

	public FutureQueue() {
		futureQueue = new ConcurrentLinkedQueue<Future<V>>();
		lock = new ReentrantLock();
	}

	public FutureQueue(Future<V> futureFirst) {
		futureQueue = new ConcurrentLinkedQueue<Future<V>>();
		lock = new ReentrantLock();
		add(futureFirst);
	}

	public boolean add(Future<V> e) {
		lock.lock();
		try {
			return futureQueue.add(e);
		} finally {
			lock.unlock();
		}
	}

	public int size() {
		lock.lock();
		try {
			return futureQueue.size();
		} finally {
			lock.unlock();
		}
	}

	public void addQueue(FutureQueue<V> queue) {
		lock.lock();
		try {
			for (Future<V> future : queue.toArray()) {
				futureQueue.add(future);
			}
		} finally {
			lock.unlock();
		}
	}

	public boolean isEmpty() {
		return futureQueue.isEmpty();
	}

	public Future<V> peek() {
		return futureQueue.peek();
	}

	public Future<V> poll() {
		lock.lock();
		try {
			return futureQueue.poll();
		} finally {
			lock.unlock();
		}
	}

	@SuppressWarnings("unchecked")
	public Future<V>[] toArray() {
		lock.lock();
		try {
			Future<V>[] futures = new Future[futureQueue.size()];
			return futureQueue.toArray(futures);
		} finally {
			lock.unlock();
		}
	}

}
